﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace mbhxnaengine.Code.GameObject
{
    // The class representing a single cell on the game board.
    //
    class GOCell : GameObject
    {
        // An enumeration defining the relation ships between this cell
        // and its siblings.
        //
        public enum SiblingTypes
        {
            ABOVE_LEFT = 0,
            ABOVE_RIGHT,
            RIGHT,
            BELOW_RIGHT,
            BELOW_LEFT,
            LEFT,

            NUM_SIBLINGS
        };

        // Debug setting for displaying the connection of this cell with its
        // siblings.
        //
        public bool mDisplaySiblingConnections;

        // The sprite used to render this game object
        //
        private GOSprite mVisual;

        // A look up table for the color a cell should be.
        //
        private Color[] mColourLookup;

        // Stores the state of this cell.
        //
        private int mState;

        // Every cell is connected in 4 directions (except edges which connext to null).
        //
        private GOCell[] mSiblings;

        // Some debug objects for drawing the connections between this cell and its siblings.
        //
        private GameObject[] mSiblingConnections;

        // Constructor
        //
        public GOCell()
        {
            // For now, every cell has the same sprite.
            mVisual = new GOSprite();
            mVisual.LoadContent("Sprites\\circle");

            // To reprsent cell states we will change the texture colour.  We use
            // this array to determine what colour to use.
            mColourLookup = new Color[]
            {
                Color.White,
                Color.Yellow,
                Color.Orange,
                Color.Red,
                Color.Violet,
                Color.Blue,
                Color.Green,
                Color.White
            };

            // Start with an undefined state
            mState = -1;

            mSiblings = new GOCell[(int)SiblingTypes.NUM_SIBLINGS];

            mDisplaySiblingConnections = false;
        }

        // Called once, when the object is loaded.
        //
        public override void LoadContent(String fileName)
        {
        }

        // Called every frame.
        //
        public override void Update(GameTime gameTime)
        {
            mVisual.pPosition = this.pPosition;
            mVisual.pRotation = this.pRotation;
            mVisual.pScale = this.pScale;

            if (mState >= 0 && mColourLookup[mState] != mVisual.pColour && !mDisplaySiblingConnections)
            {
                mVisual.pColour = mColourLookup[mState];
            }
            else if (mDisplaySiblingConnections)
            {
                mVisual.pColour = Color.Bisque;
            }
        }

        // Called at the end of every frame.
        //
        public override void Render(SpriteBatch batch)
        {
            mVisual.Render(batch);
        }

        // Accessor for the pState property.
        //
        public int pState
        {
            get
            {
                return mState;
            }
            set
            {
                mState = value;
            }
        }

        // Properties to wrap the sibling array.
        //
        public GOCell pSiblingAboveLeft
        {
            get
            {
                return mSiblings[(int)SiblingTypes.ABOVE_LEFT];
            }
            set
            {
                mSiblings[(int)SiblingTypes.ABOVE_LEFT] = value;
                //AddDebugLine(SiblingTypes.ABOVE_LEFT);
            }
        }
        public GOCell pSiblingAboveRight
        {
            get
            {
                return mSiblings[(int)SiblingTypes.ABOVE_RIGHT];
            }
            set
            {
                mSiblings[(int)SiblingTypes.ABOVE_RIGHT] = value;
                //AddDebugLine(SiblingTypes.ABOVE_RIGHT);
            }
        }
        public GOCell pSiblingRight
        {
            get
            {
                return mSiblings[(int)SiblingTypes.RIGHT];
            }
            set
            {
                mSiblings[(int)SiblingTypes.RIGHT] = value;
                //AddDebugLine(SiblingTypes.RIGHT);

            }
        }
        public GOCell pSiblingBelowLeft
        {
            get
            {
                return mSiblings[(int)SiblingTypes.BELOW_LEFT];
            }
            set
            {
                mSiblings[(int)SiblingTypes.BELOW_LEFT] = value;
                //AddDebugLine(SiblingTypes.BELOW_LEFT);

            }
        }
        public GOCell pSiblingBelowRight
        {
            get
            {
                return mSiblings[(int)SiblingTypes.BELOW_RIGHT];
            }
            set
            {
                mSiblings[(int)SiblingTypes.BELOW_RIGHT] = value;
                //AddDebugLine(SiblingTypes.BELOW_RIGHT);
            }
        }
        public GOCell pSiblingLeft
        {
            get
            {
                return mSiblings[(int)SiblingTypes.LEFT];
            }
            set
            {
                mSiblings[(int)SiblingTypes.LEFT] = value;
                //AddDebugLine(SiblingTypes.LEFT);
            }
        }

        // Sets a reference to a sibling cell.
        //
        public void SetSibling(SiblingTypes siblingType, GOCell sibling)
        {
            mSiblings[(int)siblingType] = sibling;
        }

        public void DisplaySiblingConnections(bool display)
        {
            if (display && !mDisplaySiblingConnections)
            {
                mDisplaySiblingConnections = true;

                mSiblingConnections = new GameObject[(int)SiblingTypes.NUM_SIBLINGS];

                for (SiblingTypes i = 0; i < SiblingTypes.NUM_SIBLINGS; i++)
                {
                    mSiblingConnections[(int)i] = AddDebugLine(i);
                }
            }
            else if (!display && mDisplaySiblingConnections)
            {
                mDisplaySiblingConnections = false;

                for (int i = 0; i < (int)SiblingTypes.NUM_SIBLINGS; i++)
                {
                    GameObjectManager.pInstance.Remove(mSiblingConnections[i]);
                }
            }
        }

        // A debug helper for illustrating the connection between this cell and it's siblings.
        //
        private GameObject AddDebugLine(SiblingTypes sibling)
        {
            GameObject sib = mSiblings[(int)sibling];

            if (sib != null)
            {
                GOLine brush = new GOLine();
                brush.AddVector(new Vector2(this.pPosition.X + (this.mVisual.mTexture.Width * 0.5f), this.pPosition.Y + (this.mVisual.mTexture.Height * 0.5f)));
                brush.AddVector(new Vector2(sib.pPosition.X + (this.mVisual.mTexture.Width * 0.5f), sib.pPosition.Y + (this.mVisual.mTexture.Height * 0.5f)));
                GameObjectManager.pInstance.Add(brush);

                return brush;
            }

            return null;
        }
    }
}
